package main

import (
	"fmt"
	"sort"
)

var _ = `
15. 三数之和
给你一个整数数组 nums ，判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ，同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

注意：答案中不可以包含重复的三元组。

示例 1：

输入：nums = [-1,0,1,2,-1,-4]
输出：[[-1,-1,2],[-1,0,1]]
解释：
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意，输出的顺序和三元组的顺序并不重要。
示例 2：

输入：nums = [0,1,1]
输出：[]
解释：唯一可能的三元组和不为 0 。
示例 3：

输入：nums = [0,0,0]
输出：[[0,0,0]]
解释：唯一可能的三元组和为 0 。
 

提示：

3 <= nums.length <= 3000
-105 <= nums[i] <= 105
`

func threeSum(nums []int) [][]int {
	//sort.Slice(nums, func(i, j int) bool {
	//	return nums[i] < nums[i]
	//})
	sort.Ints(nums)

	res := make([][]int, 0)
	m := make(map[int]struct{})

	for i := 0; i < len(nums); i++ {
		target := -nums[i]
		if _, ok := m[target]; ok {
			continue
		} else {
			m[target] = struct{}{}
		}

		// 双指针 [i+1, len-1]
		for l, r := i+1, len(nums)-1; l < r; {
			current := nums[l] + nums[r]
			// 比较
			if current == target {
				res = append(res, []int{nums[i], nums[l], nums[r]})
				for l++; nums[l-1] == nums[l] && l < r; {
					l++
				}
				for r--; nums[r] == nums[r+1] && l < r; {
					r--
				}
			} else if current < target {
				for l++; nums[l-1] == nums[l] && l < r; {
					l++
				}
			} else {
				for r--; nums[r] == nums[r+1] && l < r; {
					r--
				}
			}
		}
	}

	return res
}

func main() {
	//nums1 := []int{-1, 0, 1, 2, -1, -4}
	//sums1 := threeSum(nums1)
	//fmt.Println(sums1)

	nums2 := []int{1, 2, -2, -1}
	sums2 := threeSum(nums2)
	fmt.Println(sums2)

}
